/**
 * 用于合成简单的query, and or 等条件.
 */
var sysUtil = require('util');
var radon = require('radon');
var util = radon.util;

function MongoCriteria() {
	var self = this;
	self.$propAnd = {};	//与的集合,以关键字作为属性.
	self.$andParam = []; //条件与的一个集合,{$and : []};
	self.$propOr = {};	//或的集合,以关键字作为属性.
	self.$orParam = []; //条件或的一个集合,{$or : []};

	self.$begin = 0;
	self.$end = 0;
	self.$timeZone = (new Date()).getTimezoneOffset()*60; //时区

	// 默认统计当天数据
	self.begin(Date.now());
	self.$end = self.$begin + 86399;
}


/**
 * 添加Mongo查询与条件
 *
 */
MongoCriteria.prototype.addAnd = function() {
	var len = arguments.length;
	if(len <= 0) {
		return false;
	}

	//例子: addAnd([{a:2},{c:1}])
	if(sysUtil.isArray(arguments[0])) {
		this.$andParam = this.$andParam.concat(arguments[0]);
	}
	//例子: addAnd({c:1})
	else if(sysUtil.isObject(arguments[0])) {
		util.extend(this.$propAnd, arguments[0]);
	}
	//例子: addAnd('_id', 23)
	else if(len == 2){
		this.$propAnd[arguments[0]] = arguments[1];
	}
	//例子: addAnd('_id', '$lt', 23);
	else {
		var query = {};
		query[arguments[1]] = arguments[2];
		this.$propAnd[arguments[0]] = query;
	}

	return this;
};

/**
 * 删除属性 AND 条件
 * @param  String $name 属性名称
 * @return Mix          返回原始条件参数
 */
MongoCriteria.prototype.removeAnd = function(name) {
	if(this.$propAnd[name] !== undefined) {
		var cond = this.$propAnd[name];
		delete this.$propAnd[name];
		return cond;
	}
	return null;
};

/**
 * 获取属性 AND 条件
 * @param  String $name 属性名称
 * @return Mix          返回条件参数
 */
MongoCriteria.prototype.getAnd = function(name) {
	if(this.$propAnd[name]) {
		return this.$propAnd[name];
	}
	return null;
};

/**
 * 添加Mongo查询或条件
 */
MongoCriteria.prototype.addOr = function() {
	var len = arguments.length;
	if(len <= 0) {
		return false;
	}

	//例子: addOr([{a:2},{c:1}])
	if(sysUtil.isArray(arguments[0])) {
		if(arguments[0].length === 1) {
			this.$orParam.push(arguments[0][0]);
		}
		else {
			this.$orParam.push({'$or': arguments[0]});
		}
	}
	//例子: addOr({c:1})
	else if(sysUtil.isObject(arguments[0])) {
		util.extend(this.$propOr, arguments[0]);
	}
	//例子: addOr('_id', 23)
	else if(len == 2){
		this.$propOr[arguments[0]] = arguments[1];
	}
	//例子: addOr('_id', '$lt', 23);
	else {
		var query = {};
		query[arguments[1]] = arguments[2];
		this.$propOr[arguments[0]] = query;
	}

	return this;
};

/**
 * 删除属性 OR 条件
 * @param  String $name 属性名称
 * @return Mix          返回原始条件参数
 */
MongoCriteria.prototype.removeOr = function(name) {
	if(this.$propOr[name] !== undefined) {
		var cond = this.$propOr[name];
		this.$propOr[name] = undefined;
		return cond;
	}
	return null;
};

/**
 * 获取属性 OR 条件
 * @param  String $name 属性名称
 * @return Mix          返回条件参数
 */
MongoCriteria.prototype.getOr = function(name) {
	if(this.$propOr[name]) {
		return this.$propOr[name];
	}
	return null;
};

MongoCriteria.prototype.getQuery = function(param) {
	var where;
	var prop;
	if(param && param.withTime) {
		this.addAnd(this.time(param.timeField));
	}
	var and = util.clone(this.$andParam);
	if(this.$propAnd && Object.keys(this.$propAnd).length) {
		and.push(this.$propAnd);
	}

	var or = util.clone(this.$orParam);
	var query;
	if(!util.isEmpty(this.$propOr)) {
		var list = [];
		for(prop in  this.$propOr) {
			if(this.$propOr.hasOwnProperty(prop)) {
				query = {};
				query[prop] = this.$propOr[prop];
				list.push(query);
			}
		}

		if(list.length) {
			or.push(list.length === 1 ? list[0] : {"$or": list})
		}
	}

	if(and.length && or.length) {
		where = {
			'$and': and.concat(or)
		};
	}
	else if(and.length) {
		where = and.length === 1 ? and[0] : {'$and': and};
	}
	else if(or.length) {
		where = or.length === 1 ? or[0] : {'$and': or};
	}

	return where;
};

/**
 * 设置统计数据开始时间日期
 * @param  Integer $begin 开始时间戳
 * @return Integer        返回原开始时间戳
 */
MongoCriteria.prototype.begin = function(value) {
	var old = this.$begin;
	if(value !== undefined) {
		value = this.toTimestamp(value);
		if(value > 0) {
			value -= (value - this.$timeZone) % 86400;
		}
		this.$begin = value;
	}

	return old;
};

/**
 * 设置统计数据结束时间戳
 * @param  Integer $end 结束时间戳
 * @return Integer      返回原结束时间戳
 */
MongoCriteria.prototype.end = function(value) {
	var old = this.$end;
	if(value !== undefined) {
		value = this.toTimestamp(value);
		if(value > 0) {
			value -= (value - this.$timeZone) % 86400;
			value += 86399;
		}
		this.$end = value;
	}

	return old;
};


MongoCriteria.prototype.toTimestamp = function(value) {
	if (value < 1e8 && value > 1e7){
		// YYYYMMDD 格式的日期
		value = String(value);
		value = new Date(
			value.substr(0,4)+'/'+
				value.substr(4,2)+'/'+
				value.substr(6,2)
		);
	}
	if (value instanceof Date){
		// Date Object
		if (+value){
			return Math.floor(+value/1000);
		}else {
			return 0;
		}
	}else if (value > 1e11){
		// JavaScript Timestamp
		return Math.floor(value / 1000);
	}else {
		// Unix Timestamp
		return +value || 0;
	}
};

MongoCriteria.toTimestamp = MongoCriteria.prototype.toTimestamp;

MongoCriteria.prototype.time = function(name) {
	if(!name) {
		name = 'CreateTime';
	}

	var cond = {};
	cond[name] = {
		'$gte': this.$begin
		,'$lte': this.$end
	};

	return cond;
};

MongoCriteria.prototype.getTime = function() {
	if(this.$begin || this.$end) {
		var base = {};
		if(this.$begin) {
			base['begin_time'] = this.$begin;
		}

		if(this.$end) {
			base['end_time'] = this.$end;
		}

		return base;
	}

	return null;
};

// 接口名字更方便使用.
MongoCriteria.prototype.filterOr = MongoCriteria.prototype.addOr;
MongoCriteria.prototype.filterAnd = MongoCriteria.prototype.addAnd;

exports.base = MongoCriteria;